package com.ts.api.module.api.service.impl;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.date.DateUtils;
import com.gitee.apanlh.util.reflection.CopyUtils;
import com.gitee.apanlh.util.valid.Assert;
import com.gitee.apanlh.util.valid.ValidParam;
import com.ts.api.common.constant.api.ApiBizTypeEnum;
import com.ts.api.common.constant.api.ApiEnum;
import com.ts.api.common.constant.channel.ChannelIsRegisterEnum;
import com.ts.api.common.constant.product.ProductPlanVersionEnum;
import com.ts.api.common.localcache.DistrictCache;
import com.ts.api.exp.ApiMsgException;
import com.ts.api.module.api.entity.ApiUserRequest;
import com.ts.api.module.api.entity.bo.ApiBizMatchBO;
import com.ts.api.module.api.entity.bo.ApiParameterBO;
import com.ts.api.module.api.entity.bo.ApiPreRequiredBO;
import com.ts.api.module.api.entity.bo.ApiRequiredFlowBO;
import com.ts.api.module.api.entity.bo.ApiUserRegisterBO;
import com.ts.api.module.api.entity.po.ApiKeyPO;
import com.ts.api.module.api.entity.vo.ReqApiParameterVO;
import com.ts.api.module.api.service.ApiBizApplyService;
import com.ts.api.module.api.service.ApiBizRequiredService;
import com.ts.api.module.api.service.ApiInfoFlowService;
import com.ts.api.module.api.service.ApiUserRegister;
import com.ts.api.module.channel.entity.po.ChannelUserFormFieldPO;
import com.ts.api.module.channel.entity.po.ChannelUserFormPO;
import com.ts.api.module.channel.entity.po.ChannelUserRegisterPO;
import com.ts.api.module.channel.entity.qo.ChannelUserQO;
import com.ts.api.module.channel.service.ChannelUserService;
import com.ts.api.module.channel.service.DoubleWriteUserService;
import com.ts.api.module.common.entity.DistrictPO;
import com.ts.api.module.product.biz.ProductMatchBiz;
import com.ts.api.module.product.entity.po.ProductApplyFlowPO;
import com.ts.api.module.product.entity.po.ProductPlanPO;
import com.ts.api.module.product.service.ProductPlanService;
import com.ts.api.module.product.service.ProductPlanTypeService;
import com.ts.cache.form.FormCacheService;
import com.ts.cache.form.entity.FormCache;

@Service
public class ApiInfoFlowServiceImpl implements ApiInfoFlowService {

    @Autowired
    private ChannelUserService channelUserService;
    @Autowired
    private ProductMatchBiz productMatchBiz;
    @Autowired
    private ProductPlanTypeService productPlanTypeService;
    @Autowired
    private ProductPlanService productPlanService;
    @Autowired
    private ApiBizApplyService apiBizApplyService;
    @Autowired
    private ApiBizRequiredService apiBizRequiredService;
    @Autowired
    private FormCacheService formCacheService;
    @Autowired
    private DoubleWriteUserService doubleWriteUserService;
    @Autowired
    private ApiUserRegister apiUserRegister;

    @Override
    public void allocate(ApiKeyPO apiKeyPO, ApiUserRequest apiUserRequest, boolean onlyMatchAll) {
        Long loanChannelId = apiKeyPO.getLoanChannelId();

        //  获取用户信息
        ChannelUserRegisterPO userRegisterPO = channelUserService.get(ChannelUserQO.createPhone(apiUserRequest.getPhone()));

        //  用户不存在-注册用户及表单信息
        if (ValidParam.isNull(userRegisterPO)) {
            ApiUserRegisterBO apiUserRegisterBO = apiUserRegister.applyUserRegisterByApiUser(apiUserRequest);
            userRegisterPO = apiUserRegisterBO.getUserRegisterPO();
        } else {
            Long userId = userRegisterPO.getId();
            //  更新用户信息
            ChannelUserRegisterPO updateUserPO = new ChannelUserRegisterPO();
            updateUserPO.setId(userId);
            updateUserPO.setSex(apiUserRequest.getSex());
            updateUserPO.setUserName(apiUserRequest.getUserName());
            DistrictPO districtPO = DistrictCache.getByName(apiUserRequest.getCity());
            if (ValidParam.isNotNull(districtPO)) {
                updateUserPO.setAreaCode(districtPO.getCode());
                updateUserPO.setAreaName(districtPO.getName());
            }
            updateUserPO.setIsChannelRegister(ChannelIsRegisterEnum.OLD.getType());
            doubleWriteUserService.updateUser(updateUserPO);

            //  更新用户资质
            List<FormCache> formCaches = formCacheService.get();
            List<ChannelUserFormFieldPO> listUserFormField = apiUserRequest.toListUserFormField(formCaches);
            List<ChannelUserFormPO> listChannelUserFormPO = CopyUtils.copyList(listUserFormField, ChannelUserFormPO.class);
            IteratorUtils.array(listChannelUserFormPO, t -> {
                t.setChannelId(loanChannelId);
                t.setUserId(userId);
                t.setCreateTime(DateUtils.currentTime());
            });
            doubleWriteUserService.removeByUserId(userId);
            doubleWriteUserService.batchInsertUserForm(listChannelUserFormPO);
        }

        //  撞库进件必要参数
        ReqApiParameterVO reqApiParameterVO = ReqApiParameterVO.create(apiUserRequest, apiKeyPO);

        /*  撞库逻辑 */
        //  创建普通匹配计划模式
        ApiBizMatchBO normalPlan = ApiBizMatchBO.createNormalPlan(false);
        List<ProductPlanPO> listMatchPlan = productMatchBiz.apiMatchPlan(apiKeyPO, reqApiParameterVO, normalPlan);
        if (ValidParam.isEmpty(listMatchPlan)) {
            Assert.isNotEmptyThrows(listMatchPlan, new ApiMsgException(ApiEnum.API_INFO_FLOW_MATCH_EMPTY));
        }

        List<ProductPlanPO> listExcludedMatchPlan = listMatchPlan.stream().filter(productPlanPO -> {
            if (onlyMatchAll) {
                boolean hasPlatform = productPlanTypeService.hasPlatformPlan(productPlanPO);
                boolean hasAll = ProductPlanVersionEnum.ALL.hasVersion(productPlanPO.getVersionType());
                // 不是平台计划(是机构计划) 或 是“全流程”
                return !hasPlatform || hasAll;
            }
            return true;
        }).collect(Collectors.toList());
        if (ValidParam.isEmpty(listExcludedMatchPlan)) {
            Assert.isNotEmptyThrows(listExcludedMatchPlan, new ApiMsgException(ApiEnum.API_INFO_FLOW_MATCH_EMPTY));
        }

        //  过滤出已经被当前用户分发过的计划
        List<ProductPlanPO> listAllowMatchPlan = productPlanService.filterDistributeByUser(listExcludedMatchPlan, userRegisterPO.getId());
        //  无计划分发
        if (ValidParam.isEmpty(listAllowMatchPlan)) {
            Assert.isNotEmptyThrows(listAllowMatchPlan, new ApiMsgException(ApiEnum.API_INFO_FLOW_MATCH_EXIST));
        }

        //  分发-记录进件信息
        productMatchBiz.apiAllocateByPrice(apiKeyPO, reqApiParameterVO, listAllowMatchPlan);

        /*  进件 */
        //  查询是否渠道存在该流程
        ApiRequiredFlowBO apiRequiredFlowBO = ApiRequiredFlowBO.createByApiClientId(userRegisterPO.getPhoneMd5(), apiKeyPO.getApiClientId());
        ProductApplyFlowPO productApplyFlowPO = apiBizRequiredService.requiredSucDataExchangeFlow(apiRequiredFlowBO);
        Assert.isNotNullThrows(productApplyFlowPO, new ApiMsgException(ApiEnum.API_APPLY_FLOW_ERROR));

        //  增加进件前置参数验证
        ApiPreRequiredBO apiPreRequiredBO = ApiPreRequiredBO.create(reqApiParameterVO, ApiBizTypeEnum.INFO_FLOW_APPLY, null, normalPlan);
        ApiParameterBO apiParameterBO = apiBizRequiredService.preRequiredParam(apiPreRequiredBO);
        //  进件
        apiBizApplyService.apply(apiUserRequest, apiParameterBO, productApplyFlowPO);
    }
}
